package cn.nawang.ebeim.client;

import java.io.File;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.nawang.ebeim.client.bean.BackupBean;
import cn.nawang.ebeim.client.bean.ClientConfiguration;
import cn.nawang.ebeim.client.bean.DataSource;
import cn.nawang.ebeim.client.bean.DataSourceQueue;
import cn.nawang.ebeim.client.bean.DataSourceTask;
import cn.nawang.ebeim.client.bean.RecoveryBean;
import cn.nawang.ebeim.client.bean.RecoveryQueue;
import cn.nawang.ebeim.client.bean.RecoveryTask;
import cn.nawang.ebeim.client.bean.UpDownloadFailedBean;
import cn.nawang.ebeim.client.bean.UpDownloadFailedQueue;
import cn.nawang.ebeim.client.util.ApiUtil;
import cn.nawang.ebeim.client.util.ApiVisitUtil;
import cn.nawang.ebeim.client.util.CommonMethodsUtils;
import cn.nawang.ebeim.client.util.Constants;
import cn.nawang.ebeim.client.util.DbUpDownloadFailedUtil;
import cn.nawang.ebeim.client.util.DbUtil;
import cn.nawang.ebeim.client.util.FileUtil;

public class TaskFetcherThread implements Runnable {
  private static final Logger LOG = LoggerFactory.getLogger(TaskFetcherThread.class);

  @Override
  public void run() {
    LOG.info("TaskFetcher starts to run at {}", System.currentTimeMillis());
    fetchRunningRecoveryTasks();
    while (!AppMain.stopFlag.get()) {
      fetchBackupTasks();
      fetchRecoveryTasks();
      fetchUpDownloadTryAgaginTask();

      try {
        Thread.sleep(Constants.SLEEP_SECOND_5);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

  }
  
  public void fetchUpDownloadTryAgaginTask(){
    List<UpDownloadFailedBean> beans
      = DbUpDownloadFailedUtil.getUpDownloadFailedsByStatus(DbUpDownloadFailedUtil.STATUS_RUNNING);
    String ids = "";
    for (UpDownloadFailedBean bean : beans) {
      ids += bean.getId()+",";
    }
    if(ids.length()>0){
      ids = ids.substring(0, ids.length()-1);
      DbUpDownloadFailedUtil.updateStatusByIds(DbUpDownloadFailedUtil.STATUS_QUEEING, ids);
    }
    
    for (UpDownloadFailedBean bean : beans) {
      try {
        UpDownloadFailedQueue.enqueue(bean);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  public void fetchBackupTasks() {
    LOG.debug("fetch backup datasource tasks");
    List<BackupBean> bts = DbUtil.getBackupTasks();
    for (BackupBean b : bts) {
      DataSource ds = ApiUtil.getDataSource(b.getDsId());
      if (ds == null) {
        LOG.info("datasource doesn't exist:{}", b);
        DbUtil.updateBackupTask(b.getId(), DbUtil.STATUS_ERROR);
        continue;
      }

      FileUtil.initWorkingPath(ds.getId());
      
      if(ClientConfiguration.isRunningList.get(ds.getId())!=null){
        continue;
      }
      ClientConfiguration.isRunningList.put(ds.getId(), ds);

      CommonMethodsUtils.addBackupLogProcess(ds, "手动备份");

      if (!new File(ds.getRoot()).exists() && ds.getDsType().equals(Constants.DS_TYPE_FILE)) {
        ApiUtil.updateDataSourceStatus(ds, Constants.DS_RUN_STATUS_ERROR);
        // 日志处理
        CommonMethodsUtils.backupLogProcess(ds.getId(), ds.getNextVersion().getMajorVersion(),
            ds.getNextVersion().getMinorVersion(), Constants.BACKUPLOG_STATUS_FAILED, 0l,
            "数据源目录:[" + ds.getRoot() + "]不存在");
        continue;
      }

      DataSource newDs = new DataSource();
      newDs.setId(ds.getId());
      int newCount = (ds.getCount() == null ? 1 : ds.getCount() + 1);
      // 成功备份次数加1
      newDs.setCount(newCount);
      // 执行状态
      newDs.setStatus(Constants.DS_RUN_STATUS_RUNNING);
      // 版本号
      newDs.setCurrentVersionMajor(ds.getNextVersion().getMajorVersion());
      newDs.setCurrentVersionMinor(ds.getNextVersion().getMinorVersion());
      ApiVisitUtil.updataDatasource(newDs);

      DataSourceTask dt = new DataSourceTask(ds);
      dt.setId(b.getId());
      // dt.setDataSource(newDs);
      try {
        LOG.debug("enqueue datasource task: {}", dt);
        DataSourceQueue.enqueue(dt);
        DbUtil.updateBackupTask(b.getId(), DbUtil.STATUS_RUNNING);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }

    }
  }

  public void fetchRecoveryTasks() {
    LOG.debug("fetch recovery tasks");
    List<RecoveryBean> rts = DbUtil.getRecoveryTasks();
    for (RecoveryBean r : rts) {
      RecoveryTask rt = new RecoveryTask();
      rt.setDataSourceId(r.getDsId());
      rt.setPath(r.getPath());
      rt.setVersion(r.getVersion());
      rt.setId(r.getId());
      rt.setRecoveryPath(r.getRecoveryPath());
      rt.setNid(r.getNid());
      rt.setUserClickNodePath(r.getUserClickNodePath());

      DataSource ds = ApiUtil.getDataSource(r.getDsId());
        
      if (ds == null) {
        continue;
      }
      rt.setIsEncrypt(ds.getIsEncrypt());
      rt.setCreateUserId(ds.getCreateUserId());
      try {
        LOG.debug("enqueue recovery task: {}", rt);
        RecoveryQueue.enqueue(rt);
        DbUtil.updateRecoveryTask(r.getId(), DbUtil.STATUS_RUNNING);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
  
  public void fetchRunningRecoveryTasks() {
      LOG.debug("fetch recovery tasks");
      List<RecoveryBean> rts = DbUtil.getRunningRecoveryTasks();
      for (RecoveryBean r : rts) {
        RecoveryTask rt = new RecoveryTask();
        rt.setDataSourceId(r.getDsId());
        rt.setPath(r.getPath());
        rt.setVersion(r.getVersion());
        rt.setId(r.getId());
        rt.setRecoveryPath(r.getRecoveryPath());
        rt.setNid(r.getNid());
        rt.setUserClickNodePath(r.getUserClickNodePath());

        DataSource ds = null;
        
        ds = ApiUtil.getDataSource(r.getDsId());
        
        rt.setIsEncrypt(ds.getIsEncrypt());
        try {
          LOG.debug("enqueue recovery task: {}", rt);
          RecoveryQueue.enqueue(rt);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
}
